package com.hfy.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hfy.admin.mapper.*;
import com.hfy.admin.service.ApprovalService;
import com.hfy.feign.IMusicClient;
import com.hfy.model.Bo.AlbumBo;
import com.hfy.model.dto.admin.ApprovalAlbumApplyDto;
import com.hfy.model.dto.admin.ApprovalMusicApplyDto;
import com.hfy.model.dto.admin.ApprovalMusicianApplyDto;
import com.hfy.model.po.admin.*;
import com.hfy.model.vo.admin.ApplyAlbumVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import result.Result;

import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ author 韩
 * time: 2024/12/24 13:01
 */
@Service
public class ApprovalServiceImpl implements ApprovalService {

    @Autowired
    private ApplyMusicianMapper applyMusicianMapper;

    @Autowired
    private ApplyMusicMapper applyMusicMapper;

    @Autowired
    private ApplyAlbumMapper applyAlbumMapper;

    @Autowired
    private HttpSession session;
    @Autowired
    private IMusicClient musicClient;

    @Autowired
    private ApprovalLogMusicianMapper approvalLogMusicianMapper;

    @Autowired
    private ApprovalLogMusicMapper approvalLogMusicMapper;

    @Autowired
    private ApprovalLogAlbumMapper approvalLogAlbumMapper;


    @Override
    public Result queryMusicianPages(Integer status, String type, String area, int page, int size) {
        LambdaQueryWrapper<ApplyMusicianPo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApplyMusicianPo::getIsDie, 0); // 逻辑删除过滤
        if (status != null) {
            queryWrapper.eq(ApplyMusicianPo::getStatus, status);
        }
        if (type != null && !type.isEmpty()) {
            queryWrapper.eq(ApplyMusicianPo::getType, type);
        }
        if (area != null && !area.isEmpty()) {
            queryWrapper.like(ApplyMusicianPo::getArea, area);
        }
        queryWrapper.orderByDesc(ApplyMusicianPo::getApplyTime);

        Page<ApplyMusicianPo> resultPage = new Page<>(page, size);
        return Result.ok(applyMusicianMapper.selectPage(resultPage, queryWrapper));
    }

    @Override
    public Result queryAlbumPages(Integer status, Integer styleId,
                                  LocalDateTime startDate, LocalDateTime endDate, int page, int size) {
        // 去分页查询一下专辑
        LambdaQueryWrapper<ApplyAlbumPo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper
                .eq(status != null, ApplyAlbumPo::getStatus, status)
                .ge(startDate != null, ApplyAlbumPo::getApplyTime, startDate)
                .le(endDate != null, ApplyAlbumPo::getApplyTime, endDate);

        queryWrapper.orderByDesc(ApplyAlbumPo::getApplyTime);
        // 分页查询
        Page<ApplyAlbumPo> resultPage = new Page<>(page, size);
        Page<ApplyAlbumPo> poPage = applyAlbumMapper.selectPage(resultPage, queryWrapper);
        // Po 转 Vo
        List<ApplyAlbumVo> voList = poPage.getRecords().stream()
                .map(this::convertPoToVo) // 转换方法
                .collect(Collectors.toList());
        // 获取专辑id的列表
        List<Integer> idList = poPage.getRecords().stream().map(ApplyAlbumPo::getAlbumId)
                .collect(Collectors.toList());
        // 查询到对应专辑的信息
        List<AlbumBo> albumBos = musicClient.pageAlbumByIdList(idList);
        for (int i = 0; i < voList.size(); i++) {
            BeanUtil.copyProperties(albumBos.get(i), voList.get(i));
        }
        // 包装返回结果
        Page<ApplyAlbumVo> voPage = new Page<>();
        voPage.setRecords(voList);
        voPage.setCurrent(poPage.getCurrent());
        voPage.setSize(poPage.getSize());
        voPage.setTotal(poPage.getTotal());
        return Result.ok(voPage);
    }

    @Override
    @Transactional
    public Result approvalMusicApply(ApprovalMusicApplyDto dto) {

        if (BeanUtil.isEmpty(dto)) return Result.error("参数不能为空");
        String des = dto.getDes();
        Integer toStatus = dto.getToStatus();
        // 申请id
        Integer applyId = dto.getId();
        if (StringUtils.isBlank(des)) {
            return Result.error("批注不能为空");
        }
        Integer adminId = Integer.valueOf(String.valueOf(session.getAttribute("id")));

        // 前面和处理音乐人审批逻辑大致相同，只是根据通过和拒绝不同，对专辑状态也进行操作，通过不操作，但拒绝的话，转移也要改成拒绝状态
        // rr级别 去用update操作一下，where是排他锁，可以查到最新数据
        LambdaUpdateWrapper<ApplyMusicPo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ApplyMusicPo::getStatus, toStatus)
                .eq(ApplyMusicPo::getId, applyId)
                .eq(ApplyMusicPo::getStatus, 0);
        int updateCount = applyMusicMapper.update(updateWrapper);
        if (updateCount == 0) {
            // 说明一定被人改变了，而且是已经提交了的，因为特别这需要考虑专辑的状态和音乐的状态，所以这里就不过度增加代码复杂度了
            // 直接前端刷新一下获取最新数据即可
            return Result.error("无法执行该操作，已经被其他人处理");
        }

        // 在音乐处理日志表插入一条信息

        ApprovalLogMusicPo approvalLogMusicPo = new ApprovalLogMusicPo();
        approvalLogMusicPo.setApplyMusicId(applyId);
        approvalLogMusicPo.setApprovalType(toStatus.byteValue());
        approvalLogMusicPo.setApprovalTime(LocalDateTime.now());
        approvalLogMusicPo.setDes(des);
        approvalLogMusicPo.setAdminId(adminId);

        approvalLogMusicMapper.insert(approvalLogMusicPo);
        return Result.ok();
    }

    @Override
    @Transactional
    public Result approvalAlbumApply(ApprovalAlbumApplyDto dto) {
        if (BeanUtil.isEmpty(dto)) {
            return Result.error("参数不能为空");
        }
        String des = dto.getDes();
        Integer applyId = dto.getId();
        Integer toStatus = dto.getToStatus();
        if (StringUtils.isBlank(des)) {
            return Result.error("批注不能为空");
        }
        Integer adminId = Integer.valueOf(String.valueOf(session.getAttribute("id")));

        // 要求过滤一下，到底能不能进行该通过或拒绝操作
        LambdaQueryWrapper<ApplyMusicPo> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.eq(ApplyMusicPo::getApplyAlbumId, applyId)
                .eq(ApplyMusicPo::getStatus, 0);
        // 看未处理的有多少
        Long unDoCount = applyMusicMapper.selectCount(queryWrapper1);
        if (unDoCount != 0) {
            // 如果有未处理的话
            return Result.error("必须审批完全部音乐，才可以审批整张专辑");
        }
        // 如果想要通过一张专辑，它的所有音乐必须全部通过
        if (toStatus == 1) {
            LambdaQueryWrapper<ApplyMusicPo> queryWrapper2 = Wrappers.lambdaQuery();
            queryWrapper2.eq(ApplyMusicPo::getApplyAlbumId, applyId)
                    .eq(ApplyMusicPo::getStatus, 2);
            Long doRejectCount = applyMusicMapper.selectCount(queryWrapper1);
            if (doRejectCount > 0) {
                // 有音乐是拒绝状态
                return Result.error("该专辑无法通过，因为有音乐未通过，请重新审批并给上整张专辑的批注");

            }
        }

        // 筛完 然后就可以进行业务操作了
        // rr级别 去用update操作一下，where是排他锁，可以查到最新数据
        LambdaUpdateWrapper<ApplyAlbumPo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ApplyAlbumPo::getStatus, toStatus)
                .eq(ApplyAlbumPo::getId, applyId)
                .eq(ApplyAlbumPo::getStatus, 0);
        int updateCount = applyAlbumMapper.update(updateWrapper);
        if (updateCount == 0) {
            // 说明一定被人改变了，而且是已经提交了的，因为特别这需要考虑专辑的状态和音乐的状态，所以这里就不过度增加代码复杂度了
            // 直接前端刷新一下获取最新数据即可
            return Result.error("无法执行该操作，帖子已经被其他人处理");
        }

        // 在音乐处理日志表插入一条信息
        ApprovalLogAlbumPo approvalLogAlbumPo = new ApprovalLogAlbumPo();
        approvalLogAlbumPo.setApplyAlbumId(applyId);
        approvalLogAlbumPo.setApprovalType(toStatus.byteValue());
        approvalLogAlbumPo.setApprovalTime(LocalDateTime.now());
        approvalLogAlbumPo.setDes(des);
        approvalLogAlbumPo.setAdminId(adminId);

        approvalLogAlbumMapper.insert(approvalLogAlbumPo);
        return Result.ok();

    }


    @Override
    @Transactional
    public Result approvalMusicianApply(ApprovalMusicianApplyDto dto) {
        if (BeanUtil.isEmpty(dto)) {
            return Result.error("参数不能为空");
        }

        Integer toStatus = dto.getToStatus();
        // 申请id
        Integer applyId = dto.getId();
        String des = dto.getDes();
        if (session.getAttribute("id") == null) {
            return Result.error("可能是服务器重启或者遇到一些问题，无法在session中获取到信息");
        }
        Integer adminId = Integer.valueOf(String.valueOf(session.getAttribute("id")));
        // rr级别 去用update操作一下，where是排他锁，可以查到最新数据
        LambdaUpdateWrapper<ApplyMusicianPo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ApplyMusicianPo::getStatus, toStatus)
                .eq(ApplyMusicianPo::getId, applyId)
                .eq(ApplyMusicianPo::getStatus, 0);
        int updateCount = applyMusicianMapper.update(updateWrapper);
        if (updateCount == 0) {
            // 说明一定被人改变了，而且是已经提交了的，其他人已经无法更改，所以现在去查一下，普通读就可以解决问题
            LambdaQueryWrapper<ApplyMusicianPo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(ApplyMusicianPo::getStatus).eq(ApplyMusicianPo::getId, applyId);
            ApplyMusicianPo po = applyMusicianMapper.selectOne(queryWrapper);
            // 前端拿到这个值，提醒并把这个值置成响应状态
            if (po.getStatus() == 1) {
                return Result.ok(po.getStatus() , "无法执行该操作,因为该帖子已经被其他人通过处理");
            } else if (po.getStatus() == 2) {
                return Result.ok(po.getStatus() , "无法执行该操作,因为该操作已经被其他人拒绝处理");
            } else {
                return Result.error("G了");
            }
        }
        // 执行成功, 就插入一条信息
        ApprovalLogMusicianPo approvalLogMusicianPo = new ApprovalLogMusicianPo();
        approvalLogMusicianPo.setApprovalTime(LocalDateTime.now());
        approvalLogMusicianPo.setDes(des);
        approvalLogMusicianPo.setAdminId(adminId);
        approvalLogMusicianPo.setApplyId(applyId);
        approvalLogMusicianPo.setApprovalStatus(toStatus.byteValue());
        approvalLogMusicianMapper.insert(approvalLogMusicianPo);
        return Result.ok();
    }

    private ApplyAlbumVo convertPoToVo(ApplyAlbumPo po) {
        ApplyAlbumVo vo = BeanUtil.copyProperties(po, ApplyAlbumVo.class);// 简单复制属性
        return vo;
    }
}
